<?php
include_once('DbHelper.php');
include_once('Product.php');
/*
	组卷的算法：
	1、获取符合要求的所有题目，发放如刀questionBuffer中
	2、将组卷中按照相似率获取所需要相同的题目加入到sameQuestionBuffer中,并从questionBuffer中剔除
	3、将sameQuestionBuffer中的加入到tempBuffer中，再随机从questionBuffer中取出所需数量的不同题补充完整tempBuffer中，然后将题目放入wasteBuffer中，并计算现在的难度
	4、进行循环，如果难度高了就将难度最高的题目剔除，随机取出一条难度小于平均值的记录，反之异然，知道取出难度符合难度范围区间的题组(在输入的±errorZone间)，如果在结束前questionBuffer就空了，则提示符合题目数不足
	5、完成后将tempBuffer中的数据加入product[]中,将wasteBuffer中的都加入到questionBuffer中
	6、如果出卷数量不止一个，则从第3步再来一次
 */
class OneChooseProduct extends Product //有些类似array_rand()选出的个数少于数组个数报警告这些都没有处理
{
	private $errorZone=0.05;//误差值
	private $product;//返回的产品,筛选出的
	private $questionBuffer;//题目容器
	private $sameQuestionBuffer;//根据相似率获取相同的题目
	private $tempBuffer;//临时存储一次性的题目，等到符合要求后加入到product中
	private $wasteBuffer;//将不符合要求的题目暂时放入这里
	private $sameQuestionNum;//不同试卷中相同的题目

	public function setErrorZone($errorZone)//设置误差值
	{
		$this->errorZone=$errorZone;
	}

	public function __construct()//相识于DbHelper,使用数据库
	{
		$dbHelper=new DbHelper('choose');
		$this->questionBuffer=$dbHelper
					->where('status=3')
					->field('chooseId,question,A,B,C,D,correct,content,difficulty')
					->order('difficulty DESC')
					->select();
		$this->sameQuestionNum=round($this->getQuestionNum()*$this->getRate(),0);
		$same_question_key=array_rand($this->questionBuffer,$this->sameQuestionNum);
		if (is_array($same_question_key)) {
			foreach ($same_question_key as $key_name) {
				$this->sameQuestionBuffer[]=$this->questionBuffer[$key_name];
				array_splice($this->questionBuffer, $key_name,1);
			}
		}else{
			$this->sameQuestionBuffer[]=$this->questionBuffer[$same_question_key];
			array_splice($this->questionBuffer, $same_question_key,1);
		}
		
		$this->tempBuffer=$this->sameQuestionBuffer;
		$this->product=array();
	}

	public function getProperties(){//从这个方法返回所需的数据
		for ($i=0; $i < $this->getPaperNum(); $i++) { 
			$this->fillTempBuffer();
			while ($this->countBufferDifficulty()<($this->getDifficulty()-$this->errorZone)
						||$this->countBufferDifficulty()>($this->getDifficulty()+$this->errorZone)) {
				if (empty($this->questionBuffer)) {
					return 'error : not enough question to make test paper';
				}
				$this->adjustTempBuffer($this->countBufferDifficulty()<($this->getDifficulty()-$this->errorZone)?0:1);
			}
			$this->questionBuffer=array_merge($this->questionBuffer,$this->wasteBuffer);
			$this->wasteBuffer=array();
			if (!empty($this->questionBuffer)) {
				array_multisort(array_column($this->questionBuffer,'difficulty'),SORT_ASC,SORT_NUMERIC,$this->questionBuffer);
			}
			$this->product[]=$this->tempBuffer;
			$this->tempBuffer=$this->sameQuestionBuffer;
		}
		return empty($this->product)?array():$this->product;
	}

	private function fillTempBuffer()//填充临时容器
	{
		$question_need=$this->getQuestionNum()-$this->sameQuestionNum;
		$fill_question_key=array_rand($this->questionBuffer,$question_need);
		if (is_array($fill_question_key)) {
			foreach ($fill_question_key as $key_name) {
				$this->tempBuffer[]=$this->questionBuffer[$key_name];
				$this->wasteBuffer[]=$this->questionBuffer[$key_name];
				array_splice($this->questionBuffer,$key_name,1);
			}
		}else{
			$this->tempBuffer[]=$this->questionBuffer[$fill_question_key];
			$this->wasteBuffer[]=$this->questionBuffer[$fill_question_key];
			array_splice($this->questionBuffer,$fill_question_key,1);
		}
		// $this->test();
	}

	/* @return int*/
	private function countBufferDifficulty()//计算现在的难度
	{
		$temp_buffer_difficulty=array_column($this->tempBuffer,'difficulty');//TODO:这里是诟病，只能这样了
		return (array_sum($temp_buffer_difficulty)/$this->getQuestionNum());
	}

	private function adjustTempBuffer($type)//调整临时容器中数据，type=0 难度偏小 ，type=1难度偏大
	{
		$dif_key_value=array_column($this->tempBuffer,'difficulty');
		array_multisort($dif_key_value,SORT_ASC,SORT_NUMERIC,$this->temp_buffer_difficulty);
		if ($type) {//难度偏大,去掉最后一个
			$item_out=array_pop($this->tempBuffer);
			$item_in=array_shift($this->questionBuffer,0,1);
		}else{//难度偏小,去掉第一个
			$item_out=array_shift($this->tempBuffer,0,1);
			$item_in=array_pop($this->questionBuffer);
		}
		$this->wasteBuffer[]=$item_out;
		$this->tempBuffer[]=$item_in;
	}

	private function test()
	{
		echo '---------------sameQuestionBuffer';
		print_r($this->sameQuestionBuffer);
		echo '---------------tempBuffer';
		print_r($this->tempBuffer);
		echo '---------------questionBuffer';
		print_r($this->questionBuffer);
		echo '---------------wasteBuffer';
		print_r($this->wasteBuffer);
		echo '---------------sameQuestionNum';
		echo $this->sameQuestionNum;
		exit();
	}
}